import math
from awesum import Game, Drawable, Vector3, Quaternion, Key, Player

from weapons import Weapon

class Car(Drawable):
	"""Car, user controlled"""
	MAX_SPEED = .6		#Fastest car can go normally
	MAX_BOOST_SPEED = 1.5	#Fastest boosted speed
	MIN_SPEED = -.4		#Fastest speed for reverse
	ANGLE_INC = 1.5		#Angle increment for turning
	def __init__(self, type=Player.Type.LOCAL):
		super(Car, self).__init__(Drawable.Traits.GL | Drawable.Traits.MOVE)
		self.scale = Vector3(5, 5, 5)	#Scale values
		self.speedInc = 0.02			#Rate to increase speed/step
		self.boost = 0.					#Amt to boost speed
		self.accelDir = 0				#1=accel fwd, -1=accel backward
		self.frictionInc = 0.005		#Rate to reduce speed/step
		self.hoverBase = .5				#Height to hover
		self.hoverAdd = 0.				#Changing value that gets added to hoverBase
		self.hoverAddAng = 0.			#Cycling angle to calculate hoverAdd
		self.moved = Vector3()			#Actual vector moved last
		self.curTrackPart = None
		self.shootWait = False
	
	def load(self, game=None):
		Weapon.loadModels(game)
		self.gl.id = game.loadModel("ship.stl", Game.ModelType.STL_BIN)
		super(Car, self).load(game)
		self.gl.scaleV(Vector3(5., 5., 5.))
		self.gl.translate = Vector3(0., self.hoverBase, 0.)
		self.move.drawRotation = True
		self.move.quat = Quaternion().setEulerDeg(Vector3(.001, 180., .001))
		self.move.updateRot()
	
	def draw(self):
		self.game.setColor(0., 1., 0.)
		super(Car, self).draw()
	
	def step(self):
		if self.move.speed < .5 or not self.hoverAdd == 0:
			self.hoverAddAng += 3.
			self.hoverAddAng %= 360.
			self.hoverAdd = math.sin(self.hoverAddAng * math.pi/180) * .2
		self.gl.translate.y = self.hoverBase + self.hoverAdd
		#else:
		#	self.hoverAdd = 0
		#	self.hoverAddAng = 0
	
	
		keys = self.game.keys
		
		#Button 2, keyboard up - accelerate
		if Key.UP in keys or self.game.gamepad.b2:
			self.accelDir = 1
			self.accelerate()
		#Button 1, keyboard down - brake/reverse
		elif Key.DOWN in keys or self.game.gamepad.b3:#b1
			self.accelDir = -1
			self.reverse()
		else:
			self.accelDir = 0
		
		if Key.SPACE in keys or self.game.gamepad.b1 or self.game.gamepad.b8:
			if not self.shootWait:
				self.fireWeapon()
				self.shootWait = True
		else:
			self.shootWait = False
		
		#D-pad left/right, keyboard left/right - turn car
		if Key.LEFT in keys or self.game.gamepad.left or self.game.gamepad.b5:
			self.beginLeftTurn(max(self.move.speed, 1))
		elif Key.RIGHT in keys or self.game.gamepad.right or self.game.gamepad.b7:
			self.beginRightTurn(max(self.move.speed, 1))
		else:
			self.endTurn()
		
		#Analog 1 - move the camera's focus point around
		#if self.game.gamepad.analog1x:
		#	xAng = self.game.gamepad.analog1x * 20 #degrees to look left & right
		#	self.game.cam.view.x += 10 * math.sin((self.rot.y + xAng) * math.pi/180)
		#	self.game.cam.view.z += 10 * math.cos((self.rot.y + xAng) * math.pi/180)
		#if self.game.gamepad.analog1y:
		#	self.game.cam.view.y += 5 * self.game.gamepad.analog1y
		
		#Analog 1 - move the camera's focus point around
		anX = self.game.gamepad.analog1x
		if anX > .15:
			self.beginRightTurn(anX * 2.5)
		elif anX < -.15:
			self.beginLeftTurn(-anX * 2.5)
		else:
			self.endTurn()
			
		anY = self.game.gamepad.analog1y
		if anY < -.15:
			self.boost = .01 * anY
		else:
			self.boost = 0.
		
		#Add friction until the car stops
		if self.move.speed > 0.:
			self.move.speed -= self.frictionInc
			if self.move.speed < 0.:
				self.move.speed = 0.
		elif self.move.speed < 0.:
			self.move.speed += self.frictionInc
			if self.move.speed > 0.:
				self.move.speed = 0.
		self._limitSpeed()
		
		self.move.updateRot()
	
	def beginLeftTurn(self, mult=1):
		if self.accelDir == -1: #reverse
			q = Quaternion().setEulerDeg(Vector3(0., -Car.ANGLE_INC * mult, 0.))
			self.move.quat *= q
		else: #forward
			q = Quaternion().setEulerDeg(Vector3(0., Car.ANGLE_INC * mult, 0.))
			self.move.quat *= q
	
	def beginRightTurn(self, mult=1):
		if self.accelDir == -1: #reverse
			q = Quaternion().setEulerDeg(Vector3(0., Car.ANGLE_INC * mult, 0.))
			self.move.quat *= q
		else: #forward
			q = Quaternion().setEulerDeg(Vector3(0., -Car.ANGLE_INC * mult, 0.))
			self.move.quat *= q
	
	def endTurn(self):
		pass
	
	def accelerate(self):
		self.move.speed += self.speedInc + self.boost
		self._limitSpeed()
	
	def reverse(self):
		self.move.speed -= (self.speedInc / 2)
		self._limitSpeed()
	
	def fireWeapon(self):
		missile = Weapon(self)
		missile.load(self.game)
		self.game.scene.drawables.append(missile)
	
	def _limitSpeed(self):
		#Enforce speed limits
		if self.boost:
			max = Car.MAX_BOOST_SPEED
		else:
			max = Car.MAX_SPEED
		
		if self.move.speed > max:
			diff = self.move.speed - max
			self.move.speed -= diff * .1
		elif self.move.speed < Car.MIN_SPEED:
			self.move.speed = Car.MIN_SPEED
